﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using ZoneFiveSoftware.Common.Data.Fitness;
using System.ComponentModel.Design;
using System.Collections;

namespace HackersDiet
{
    public partial class HDControl : UserControl
    {
        public HDControl()
        {
            InitializeComponent();
            //this.chart1 = (Chart)this.Site.Container.Components["Chart"];
        }

        //public HDControl(HDControl cpy) : this()
        //{
        //    //InitializeComponent();
        //    this.chart1 = cpy.chart1;
        //}

        public ChartAreaCollection ChartAreas
        {
            get
            {
                return this.chart1.ChartAreas;
            }
        }

        public Chart Chart
        {
            get
            {
                return this.chart1;
            }
            set
            {
                this.chart1 = value;
            }
        }

        private void btnEditChart_Click(object sender, EventArgs e)
        {
            Form f = new Form();

            PropertyGrid pg = new PropertyGrid();

            pg.SelectedObject = this.chart1;
            pg.Dock = DockStyle.Fill;
            f.Controls.Add(pg);

            f.ShowDialog();
        }

        private ChartArea GetOrCreateChartArea(string name)
        {
            ChartArea ca = null;

            if (this.chart1.ChartAreas.IsUniqueName(name))
            {
                ca = new ChartArea(name);
                this.chart1.ChartAreas.Add(ca);
                ca.AxisX.IsStartedFromZero = false;
                ca.AxisX.MajorGrid.Enabled = false;
                ca.AxisY.IsStartedFromZero = false;
                ca.AxisY.MajorGrid.Enabled = false;
                ca.CursorX.IsUserEnabled = true;
                ca.CursorX.IsUserSelectionEnabled = true;
                ca.AxisX.ScaleView.Zoomable = true;
                ca.AxisX.ScrollBar.IsPositionedInside = true;
                ca.CursorY.IsUserEnabled = true;
                ca.CursorY.IsUserSelectionEnabled = true;
                ca.AxisY.ScaleView.Zoomable = true;
                ca.AxisY.ScrollBar.IsPositionedInside = true;
                ca.AxisY.Title = name;
                ca.Visible = true;
            }
            else
            {
                ca = this.chart1.ChartAreas[name];
            }

            return ca;
        }

        private Legend GetOrCreateLegend(string chartArea)
        {
            Legend l = null;

            if (this.chart1.Legends.IsUniqueName(chartArea))
            {
                l = new Legend(chartArea);
                this.chart1.Legends.Add(l);
                l.DockedToChartArea = chartArea;
                l.Docking = Docking.Bottom;
                l.Alignment = StringAlignment.Center;
                l.Enabled = true;
                l.IsDockedInsideChartArea = false;
                l.Name = chartArea;
                l.Title = chartArea;
            }
            else
            {
                l = this.chart1.Legends[chartArea];
            }

            return l;
        }

        private Series GetOrCreateSeries(string name, string chartArea)
        {
            Series s = null;

            if (this.chart1.Series.IsUniqueName(name))
            {
                s = new Series(name);
                this.chart1.Series.Add(s);

                s.XValueType = ChartValueType.Date;
                s.ChartArea = chartArea;
                s.BorderWidth = 2;
                s.ChartType = SeriesChartType.FastLine;
                s.Legend = chartArea;
                s.Enabled = (name != chartArea);
            }
            else
            {
                return this.chart1.Series[name];
            }

            return s;
        }

        private Series GetOrCreateSeries(string name)
        {
            return GetOrCreateSeries(name, name);
        }

        protected override void OnCreateControl()
        {
            base.OnCreateControl();

            Type athInfoType = typeof(IAthleteInfoEntry);
            System.Reflection.PropertyInfo[] athInfoProps = athInfoType.GetProperties();

            foreach (System.Reflection.PropertyInfo pi in athInfoProps)
            {
                if (pi.PropertyType == typeof(float) || pi.PropertyType == typeof(int) || pi.PropertyType == typeof(double))
                {
                    Series s = null;
                    
                    foreach (DateTime dt in Plugin.GetApplication().Logbook.Athlete.InfoEntries.EntryDates)
                    {
                        float value = float.NaN;

                        object tmp = pi.GetValue(Plugin.GetApplication().Logbook.Athlete.InfoEntries.EntryForDate(dt), null);

                        if (tmp is float)
                            value = (float)tmp;
                        else if (tmp is int)
                            value = (float)((int)tmp);
                        else if (tmp is double)
                            value = (float)((double)tmp);

                        if (!float.IsNaN(value) && !float.IsInfinity(value) && value > 0.0f)
                        {
                            if (s == null)
                            {
                                ChartArea ca = GetOrCreateChartArea(pi.Name);
                                Legend l = GetOrCreateLegend(ca.Name);
                                s = GetOrCreateSeries(pi.Name);
                            }

                            s.Points.AddXY(dt.ToOADate(), value);
                        }
                    }

                    if (s != null)
                    {
                        if (s.Points.Count <= 1)
                        {
                            this.chart1.ChartAreas[s.ChartArea].Visible = false;
                        }
                        else
                        {
                            Series sActual = GetOrCreateSeries(pi.Name + "-Actual", s.ChartArea);
                            this.chart1.DataManipulator.CopySeriesValues(s.Name, s.Name + "-Actual");

                            if (s.Points.Count >= 5)
                            {
                                Series sAverage = GetOrCreateSeries(pi.Name + "-Average", s.ChartArea);
                                this.chart1.DataManipulator.FinancialFormula(FinancialFormula.ExponentialMovingAverage, "5", s.Name, s.Name + "-Average");
                            }
                        }
                    }
                }
            }
            
            this.clbChartAreas.DataSource = this.chart1.ChartAreas;
            this.clbChartAreas.DisplayMember = "Name";
            //this.clbChartAreas.ValueMember = "Visible";
            this.clbChartAreas.BindingContext = new BindingContext();

            for (int i = 0; i < this.clbChartAreas.Items.Count; i++)
            {
                ChartArea ca = (ChartArea)this.clbChartAreas.Items[i];
                if (ca.Visible)
                    this.clbChartAreas.SetItemCheckState(i, CheckState.Checked);
            }

            this.clbSeries.DataSource = this.chart1.Series;
            this.clbSeries.DisplayMember = "Name";
            this.clbSeries.BindingContext = new BindingContext();

            for (int i = 0; i < this.clbSeries.Items.Count; i++)
            {
                Series s = (Series)this.clbSeries.Items[i];
                if (s.Enabled)
                    this.clbSeries.SetItemCheckState(i, CheckState.Checked);
            }
        }

        private void clbChartAreas_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            ChartArea ca = (ChartArea)this.clbChartAreas.Items[e.Index];

            ca.Visible = (e.NewValue == CheckState.Checked);
        }

        private void clbChartAreas_SelectedValueChanged(object sender, EventArgs e)
        {
            this.propertyGrid1.SelectedObject = this.clbChartAreas.SelectedItem;
        }

        private void clbSeries_SelectedValueChanged(object sender, EventArgs e)
        {
            this.propertyGrid1.SelectedObject = this.clbSeries.SelectedItem;
        }

        private void clbSeries_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            Series s = (Series)this.clbSeries.Items[e.Index];

            s.Enabled = (e.NewValue == CheckState.Checked);
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            this.chart1 = (Chart)Plugin.Container.Components["ResetChart"];
        }

        private void btnDefault_Click(object sender, EventArgs e)
        {
            this.chart1 = (Chart)Plugin.Container.Components["DefaultChart"];

            this.CreateControl();
        }
    }
}
